home *** CD-ROM | disk | FTP | other *** search
- Subject: v12i037: C News alpha release, Part12/14
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rs@uunet.UU.NET
-
- Submitted-by: utzoo!henry (Henry Spencer)
- Posting-number: Volume 12, Issue 37
- Archive-name: cnews/part12
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 12 (of 14)."
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'libc/strings/tester.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'libc/strings/tester.c'\"
- else
- echo shar: Extracting \"'libc/strings/tester.c'\" \(19922 characters\)
- sed "s/^X//" >'libc/strings/tester.c' <<'END_OF_FILE'
- X/*
- X * Test program for string(3) routines.
- X *
- X * Note that at least one Bell Labs implementation of the string
- X * routines flunks a couple of these tests -- the ones which test
- X * behavior on "negative" characters.
- X */
- X
- X#include <stdio.h>
- X#include <string.h>
- X
- X#define STREQ(a, b) (strcmp((a), (b)) == 0)
- X
- Xchar *it = "<UNSET>"; /* Routine name for message routines. */
- Xint waserror = 0; /* For exit status. */
- X
- Xchar uctest[] = "\004\203"; /* For testing signedness of chars. */
- Xint charsigned; /* Result. */
- X
- X/*
- X - check - complain if condition is not true
- X */
- Xvoid
- Xcheck(thing, number)
- Xint thing;
- Xint number; /* Test number for error message. */
- X{
- X if (!thing) {
- X printf("%s flunked test %d\n", it, number);
- X waserror = 1;
- X }
- X}
- X
- X/*
- X - equal - complain if first two args don't strcmp as equal
- X */
- Xvoid
- Xequal(a, b, number)
- Xchar *a;
- Xchar *b;
- Xint number; /* Test number for error message. */
- X{
- X check(a != NULL && b != NULL && STREQ(a, b), number);
- X}
- X
- Xchar one[50];
- Xchar two[50];
- X
- X#ifdef UNIXERR
- X#define ERR 1
- X#endif
- X#ifdef BERKERR
- X#define ERR 1
- X#endif
- X#ifdef ERR
- Xint f;
- Xextern char *sys_errlist[];
- Xextern int sys_nerr;
- Xextern int errno;
- X#endif
- X
- X/* ARGSUSED */
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X /*
- X * First, establish whether chars are signed.
- X */
- X if (uctest[0] < uctest[1])
- X charsigned = 0;
- X else
- X charsigned = 1;
- X
- X /*
- X * Then, do the rest of the work. Split into two functions because
- X * some compilers get unhappy about a single immense function.
- X */
- X first();
- X second();
- X
- X exit((waserror) ? 1 : 0);
- X}
- X
- Xfirst()
- X{
- X /*
- X * Test strcmp first because we use it to test other things.
- X */
- X it = "strcmp";
- X check(strcmp("", "") == 0, 1); /* Trivial case. */
- X check(strcmp("a", "a") == 0, 2); /* Identity. */
- X check(strcmp("abc", "abc") == 0, 3); /* Multicharacter. */
- X check(strcmp("abc", "abcd") < 0, 4); /* Length mismatches. */
- X check(strcmp("abcd", "abc") > 0, 5);
- X check(strcmp("abcd", "abce") < 0, 6); /* Honest miscompares. */
- X check(strcmp("abce", "abcd") > 0, 7);
- X check(strcmp("a\203", "a") > 0, 8); /* Tricky if char signed. */
- X if (charsigned) /* Sign-bit comparison. */
- X check(strcmp("a\203", "a\003") < 0, 9);
- X else
- X check(strcmp("a\203", "a\003") > 0, 9);
- X
- X /*
- X * Test strcpy next because we need it to set up other tests.
- X */
- X it = "strcpy";
- X check(strcpy(one, "abcd") == one, 1); /* Returned value. */
- X equal(one, "abcd", 2); /* Basic test. */
- X
- X (void) strcpy(one, "x");
- X equal(one, "x", 3); /* Writeover. */
- X equal(one+2, "cd", 4); /* Wrote too much? */
- X
- X (void) strcpy(two, "hi there");
- X (void) strcpy(one, two);
- X equal(one, "hi there", 5); /* Basic test encore. */
- X equal(two, "hi there", 6); /* Stomped on source? */
- X
- X (void) strcpy(one, "");
- X equal(one, "", 7); /* Boundary condition. */
- X
- X /*
- X * strcat
- X */
- X it = "strcat";
- X (void) strcpy(one, "ijk");
- X check(strcat(one, "lmn") == one, 1); /* Returned value. */
- X equal(one, "ijklmn", 2); /* Basic test. */
- X
- X (void) strcpy(one, "x");
- X (void) strcat(one, "yz");
- X equal(one, "xyz", 3); /* Writeover. */
- X equal(one+4, "mn", 4); /* Wrote too much? */
- X
- X (void) strcpy(one, "gh");
- X (void) strcpy(two, "ef");
- X (void) strcat(one, two);
- X equal(one, "ghef", 5); /* Basic test encore. */
- X equal(two, "ef", 6); /* Stomped on source? */
- X
- X (void) strcpy(one, "");
- X (void) strcat(one, "");
- X equal(one, "", 7); /* Boundary conditions. */
- X (void) strcpy(one, "ab");
- X (void) strcat(one, "");
- X equal(one, "ab", 8);
- X (void) strcpy(one, "");
- X (void) strcat(one, "cd");
- X equal(one, "cd", 9);
- X
- X /*
- X * strncat - first test it as strcat, with big counts, then
- X * test the count mechanism.
- X */
- X it = "strncat";
- X (void) strcpy(one, "ijk");
- X check(strncat(one, "lmn", 99) == one, 1); /* Returned value. */
- X equal(one, "ijklmn", 2); /* Basic test. */
- X
- X (void) strcpy(one, "x");
- X (void) strncat(one, "yz", 99);
- X equal(one, "xyz", 3); /* Writeover. */
- X equal(one+4, "mn", 4); /* Wrote too much? */
- X
- X (void) strcpy(one, "gh");
- X (void) strcpy(two, "ef");
- X (void) strncat(one, two, 99);
- X equal(one, "ghef", 5); /* Basic test encore. */
- X equal(two, "ef", 6); /* Stomped on source? */
- X
- X (void) strcpy(one, "");
- X (void) strncat(one, "", 99);
- X equal(one, "", 7); /* Boundary conditions. */
- X (void) strcpy(one, "ab");
- X (void) strncat(one, "", 99);
- X equal(one, "ab", 8);
- X (void) strcpy(one, "");
- X (void) strncat(one, "cd", 99);
- X equal(one, "cd", 9);
- X
- X (void) strcpy(one, "ab");
- X (void) strncat(one, "cdef", 2);
- X equal(one, "abcd", 10); /* Count-limited. */
- X
- X (void) strncat(one, "gh", 0);
- X equal(one, "abcd", 11); /* Zero count. */
- X
- X (void) strncat(one, "gh", 2);
- X equal(one, "abcdgh", 12); /* Count and length equal. */
- X
- X /*
- X * strncmp - first test as strcmp with big counts, then test
- X * count code.
- X */
- X it = "strncmp";
- X check(strncmp("", "", 99) == 0, 1); /* Trivial case. */
- X check(strncmp("a", "a", 99) == 0, 2); /* Identity. */
- X check(strncmp("abc", "abc", 99) == 0, 3); /* Multicharacter. */
- X check(strncmp("abc", "abcd", 99) < 0, 4); /* Length unequal. */
- X check(strncmp("abcd", "abc", 99) > 0, 5);
- X check(strncmp("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
- X check(strncmp("abce", "abcd", 99) > 0, 7);
- X check(strncmp("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
- X if (charsigned) /* Sign-bit comparison. */
- X check(strncmp("a\203", "a\003", 2) < 0, 9);
- X else
- X check(strncmp("a\203", "a\003", 2) > 0, 9);
- X check(strncmp("abce", "abcd", 3) == 0, 10); /* Count limited. */
- X check(strncmp("abce", "abc", 3) == 0, 11); /* Count == length. */
- X check(strncmp("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
- X check(strncmp("abc", "def", 0) == 0, 13); /* Zero count. */
- X
- X /*
- X * strncpy - testing is a bit different because of odd semantics
- X */
- X it = "strncpy";
- X check(strncpy(one, "abc", 4) == one, 1); /* Returned value. */
- X equal(one, "abc", 2); /* Did the copy go right? */
- X
- X (void) strcpy(one, "abcdefgh");
- X (void) strncpy(one, "xyz", 2);
- X equal(one, "xycdefgh", 3); /* Copy cut by count. */
- X
- X (void) strcpy(one, "abcdefgh");
- X (void) strncpy(one, "xyz", 3); /* Copy cut just before NUL. */
- X equal(one, "xyzdefgh", 4);
- X
- X (void) strcpy(one, "abcdefgh");
- X (void) strncpy(one, "xyz", 4); /* Copy just includes NUL. */
- X equal(one, "xyz", 5);
- X equal(one+4, "efgh", 6); /* Wrote too much? */
- X
- X (void) strcpy(one, "abcdefgh");
- X (void) strncpy(one, "xyz", 5); /* Copy includes padding. */
- X equal(one, "xyz", 7);
- X equal(one+4, "", 8);
- X equal(one+5, "fgh", 9);
- X
- X (void) strcpy(one, "abc");
- X (void) strncpy(one, "xyz", 0); /* Zero-length copy. */
- X equal(one, "abc", 10);
- X
- X (void) strncpy(one, "", 2); /* Zero-length source. */
- X equal(one, "", 11);
- X equal(one+1, "", 12);
- X equal(one+2, "c", 13);
- X
- X (void) strcpy(one, "hi there");
- X (void) strncpy(two, one, 9);
- X equal(two, "hi there", 14); /* Just paranoia. */
- X equal(one, "hi there", 15); /* Stomped on source? */
- X
- X /*
- X * strlen
- X */
- X it = "strlen";
- X check(strlen("") == 0, 1); /* Empty. */
- X check(strlen("a") == 1, 2); /* Single char. */
- X check(strlen("abcd") == 4, 3); /* Multiple chars. */
- X
- X /*
- X * strchr
- X */
- X it = "strchr";
- X check(strchr("abcd", 'z') == NULL, 1); /* Not found. */
- X (void) strcpy(one, "abcd");
- X check(strchr(one, 'c') == one+2, 2); /* Basic test. */
- X check(strchr(one, 'd') == one+3, 3); /* End of string. */
- X check(strchr(one, 'a') == one, 4); /* Beginning. */
- X check(strchr(one, '\0') == one+4, 5); /* Finding NUL. */
- X (void) strcpy(one, "ababa");
- X check(strchr(one, 'b') == one+1, 6); /* Finding first. */
- X (void) strcpy(one, "");
- X check(strchr(one, 'b') == NULL, 7); /* Empty string. */
- X check(strchr(one, '\0') == one, 8); /* NUL in empty string. */
- X
- X /*
- X * index - just like strchr
- X */
- X it = "index";
- X check(index("abcd", 'z') == NULL, 1); /* Not found. */
- X (void) strcpy(one, "abcd");
- X check(index(one, 'c') == one+2, 2); /* Basic test. */
- X check(index(one, 'd') == one+3, 3); /* End of string. */
- X check(index(one, 'a') == one, 4); /* Beginning. */
- X check(index(one, '\0') == one+4, 5); /* Finding NUL. */
- X (void) strcpy(one, "ababa");
- X check(index(one, 'b') == one+1, 6); /* Finding first. */
- X (void) strcpy(one, "");
- X check(index(one, 'b') == NULL, 7); /* Empty string. */
- X check(index(one, '\0') == one, 8); /* NUL in empty string. */
- X
- X /*
- X * strrchr
- X */
- X it = "strrchr";
- X check(strrchr("abcd", 'z') == NULL, 1); /* Not found. */
- X (void) strcpy(one, "abcd");
- X check(strrchr(one, 'c') == one+2, 2); /* Basic test. */
- X check(strrchr(one, 'd') == one+3, 3); /* End of string. */
- X check(strrchr(one, 'a') == one, 4); /* Beginning. */
- X check(strrchr(one, '\0') == one+4, 5); /* Finding NUL. */
- X (void) strcpy(one, "ababa");
- X check(strrchr(one, 'b') == one+3, 6); /* Finding last. */
- X (void) strcpy(one, "");
- X check(strrchr(one, 'b') == NULL, 7); /* Empty string. */
- X check(strrchr(one, '\0') == one, 8); /* NUL in empty string. */
- X
- X /*
- X * rindex - just like strrchr
- X */
- X it = "rindex";
- X check(rindex("abcd", 'z') == NULL, 1); /* Not found. */
- X (void) strcpy(one, "abcd");
- X check(rindex(one, 'c') == one+2, 2); /* Basic test. */
- X check(rindex(one, 'd') == one+3, 3); /* End of string. */
- X check(rindex(one, 'a') == one, 4); /* Beginning. */
- X check(rindex(one, '\0') == one+4, 5); /* Finding NUL. */
- X (void) strcpy(one, "ababa");
- X check(rindex(one, 'b') == one+3, 6); /* Finding last. */
- X (void) strcpy(one, "");
- X check(rindex(one, 'b') == NULL, 7); /* Empty string. */
- X check(rindex(one, '\0') == one, 8); /* NUL in empty string. */
- X}
- X
- Xsecond()
- X{
- X /*
- X * strpbrk - somewhat like strchr
- X */
- X it = "strpbrk";
- X check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
- X (void) strcpy(one, "abcd");
- X check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
- X check(strpbrk(one, "d") == one+3, 3); /* End of string. */
- X check(strpbrk(one, "a") == one, 4); /* Beginning. */
- X check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
- X check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
- X (void) strcpy(one, "abcabdea");
- X check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
- X check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
- X check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
- X (void) strcpy(one, "");
- X check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
- X check(strpbrk(one, "") == NULL, 11); /* Both strings empty. */
- X
- X /*
- X * strstr - somewhat like strchr
- X */
- X it = "strstr";
- X check(strstr("abcd", "z") == NULL, 1); /* Not found. */
- X check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
- X (void) strcpy(one, "abcd");
- X check(strstr(one, "c") == one+2, 3); /* Basic test. */
- X check(strstr(one, "bc") == one+1, 4); /* Multichar. */
- X check(strstr(one, "d") == one+3, 5); /* End of string. */
- X check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
- X check(strstr(one, "abc") == one, 7); /* Beginning. */
- X check(strstr(one, "abcd") == one, 8); /* Exact match. */
- X check(strstr(one, "abcde") == NULL, 9); /* Too long. */
- X check(strstr(one, "de") == NULL, 10); /* Past end. */
- X check(strstr(one, "") == one+4, 11); /* Finding empty. */
- X (void) strcpy(one, "ababa");
- X check(strstr(one, "ba") == one+1, 12); /* Finding first. */
- X (void) strcpy(one, "");
- X check(strstr(one, "b") == NULL, 13); /* Empty string. */
- X check(strstr(one, "") == one, 14); /* Empty in empty string. */
- X (void) strcpy(one, "bcbca");
- X check(strstr(one, "bca") == one+2, 15); /* False start. */
- X (void) strcpy(one, "bbbcabbca");
- X check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
- X
- X /*
- X * strspn
- X */
- X it = "strspn";
- X check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
- X check(strspn("abcba", "ab") == 2, 2); /* Partial. */
- X check(strspn("abc", "qx") == 0, 3); /* None. */
- X check(strspn("", "ab") == 0, 4); /* Null string. */
- X check(strspn("abc", "") == 0, 5); /* Null search list. */
- X
- X /*
- X * strcspn
- X */
- X it = "strcspn";
- X check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
- X check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
- X check(strcspn("abc", "abc") == 0, 3); /* None. */
- X check(strcspn("", "ab") == 0, 4); /* Null string. */
- X check(strcspn("abc", "") == 3, 5); /* Null search list. */
- X
- X /*
- X * strtok - the hard one
- X */
- X it = "strtok";
- X (void) strcpy(one, "first, second, third");
- X equal(strtok(one, ", "), "first", 1); /* Basic test. */
- X equal(one, "first", 2);
- X equal(strtok((char *)NULL, ", "), "second", 3);
- X equal(strtok((char *)NULL, ", "), "third", 4);
- X check(strtok((char *)NULL, ", ") == NULL, 5);
- X (void) strcpy(one, ", first, ");
- X equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
- X check(strtok((char *)NULL, ", ") == NULL, 7);
- X (void) strcpy(one, "1a, 1b; 2a, 2b");
- X equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
- X equal(strtok((char *)NULL, "; "), "1b", 9);
- X equal(strtok((char *)NULL, ", "), "2a", 10);
- X (void) strcpy(two, "x-y");
- X equal(strtok(two, "-"), "x", 11); /* New string before done. */
- X equal(strtok((char *)NULL, "-"), "y", 12);
- X check(strtok((char *)NULL, "-") == NULL, 13);
- X (void) strcpy(one, "a,b, c,, ,d");
- X equal(strtok(one, ", "), "a", 14); /* Different separators. */
- X equal(strtok((char *)NULL, ", "), "b", 15);
- X equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
- X equal(strtok((char *)NULL, " ,"), "d", 17);
- X check(strtok((char *)NULL, ", ") == NULL, 18);
- X check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
- X (void) strcpy(one, ", ");
- X check(strtok(one, ", ") == NULL, 20); /* No tokens. */
- X (void) strcpy(one, "");
- X check(strtok(one, ", ") == NULL, 21); /* Empty string. */
- X (void) strcpy(one, "abc");
- X equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
- X check(strtok((char *)NULL, ", ") == NULL, 23);
- X (void) strcpy(one, "abc");
- X equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
- X check(strtok((char *)NULL, "") == NULL, 25);
- X (void) strcpy(one, "abcdefgh");
- X (void) strcpy(one, "a,b,c");
- X equal(strtok(one, ","), "a", 26); /* Basics again... */
- X equal(strtok((char *)NULL, ","), "b", 27);
- X equal(strtok((char *)NULL, ","), "c", 28);
- X check(strtok((char *)NULL, ",") == NULL, 29);
- X equal(one+6, "gh", 30); /* Stomped past end? */
- X equal(one, "a", 31); /* Stomped old tokens? */
- X equal(one+2, "b", 32);
- X equal(one+4, "c", 33);
- X
- X /*
- X * memcmp
- X */
- X it = "memcmp";
- X check(memcmp("a", "a", 1) == 0, 1); /* Identity. */
- X check(memcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
- X check(memcmp("abcd", "abce", 4) < 0, 3); /* Honestly unequal. */
- X check(memcmp("abce", "abcd", 4) > 0, 4);
- X check(memcmp("alph", "beta", 4) < 0, 5);
- X if (charsigned) /* Sign-bit comparison. */
- X check(memcmp("a\203", "a\003", 2) < 0, 6);
- X else
- X check(memcmp("a\203", "a\003", 2) > 0, 6);
- X check(memcmp("abce", "abcd", 3) == 0, 7); /* Count limited. */
- X check(memcmp("abc", "def", 0) == 0, 8); /* Zero count. */
- X
- X /*
- X * memchr
- X */
- X it = "memchr";
- X check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
- X (void) strcpy(one, "abcd");
- X check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
- X check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
- X check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
- X check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
- X (void) strcpy(one, "ababa");
- X check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
- X check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
- X check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
- X (void) strcpy(one, "a\203b");
- X check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
- X
- X /*
- X * memcpy
- X *
- X * Note that X3J11 says memcpy must work regardless of overlap.
- X * The SVID says it might fail.
- X */
- X it = "memcpy";
- X check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
- X equal(one, "abc", 2); /* Did the copy go right? */
- X
- X (void) strcpy(one, "abcdefgh");
- X (void) memcpy(one+1, "xyz", 2);
- X equal(one, "axydefgh", 3); /* Basic test. */
- X
- X (void) strcpy(one, "abc");
- X (void) memcpy(one, "xyz", 0);
- X equal(one, "abc", 4); /* Zero-length copy. */
- X
- X (void) strcpy(one, "hi there");
- X (void) strcpy(two, "foo");
- X (void) memcpy(two, one, 9);
- X equal(two, "hi there", 5); /* Just paranoia. */
- X equal(one, "hi there", 6); /* Stomped on source? */
- X
- X (void) strcpy(one, "abcdefgh");
- X (void) memcpy(one+1, one, 9);
- X equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
- X
- X (void) strcpy(one, "abcdefgh");
- X (void) memcpy(one+1, one+2, 7);
- X equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
- X
- X (void) strcpy(one, "abcdefgh");
- X (void) memcpy(one, one, 9);
- X equal(one, "abcdefgh", 9); /* 100% overlap. */
- X
- X /*
- X * memccpy - first test like memcpy, then the search part
- X *
- X * The SVID, the only place where memccpy is mentioned, says
- X * overlap might fail, so we don't try it. Besides, it's hard
- X * to see the rationale for a non-left-to-right memccpy.
- X */
- X it = "memccpy";
- X check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
- X equal(one, "abc", 2); /* Did the copy go right? */
- X
- X (void) strcpy(one, "abcdefgh");
- X (void) memccpy(one+1, "xyz", 'q', 2);
- X equal(one, "axydefgh", 3); /* Basic test. */
- X
- X (void) strcpy(one, "abc");
- X (void) memccpy(one, "xyz", 'q', 0);
- X equal(one, "abc", 4); /* Zero-length copy. */
- X
- X (void) strcpy(one, "hi there");
- X (void) strcpy(two, "foo");
- X (void) memccpy(two, one, 'q', 9);
- X equal(two, "hi there", 5); /* Just paranoia. */
- X equal(one, "hi there", 6); /* Stomped on source? */
- X
- X (void) strcpy(one, "abcdefgh");
- X (void) strcpy(two, "horsefeathers");
- X check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
- X equal(one, "abcdefgh", 8); /* Source intact? */
- X equal(two, "abcdefeathers", 9); /* Copy correct? */
- X
- X (void) strcpy(one, "abcd");
- X (void) strcpy(two, "bumblebee");
- X check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
- X equal(two, "aumblebee", 11);
- X check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
- X equal(two, "abcdlebee", 13);
- X (void) strcpy(one, "xyz");
- X check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
- X equal(two, "xbcdlebee", 15);
- X
- X /*
- X * memset
- X */
- X it = "memset";
- X (void) strcpy(one, "abcdefgh");
- X check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
- X equal(one, "axxxefgh", 2); /* Basic test. */
- X
- X (void) memset(one+2, 'y', 0);
- X equal(one, "axxxefgh", 3); /* Zero-length set. */
- X
- X (void) memset(one+5, 0, 1);
- X equal(one, "axxxe", 4); /* Zero fill. */
- X equal(one+6, "gh", 5); /* And the leftover. */
- X
- X (void) memset(one+2, 010045, 1);
- X equal(one, "ax\045xe", 6); /* Unsigned char convert. */
- X
- X /*
- X * bcopy - much like memcpy
- X *
- X * Berklix manual is silent about overlap, so don't test it.
- X */
- X it = "bcopy";
- X (void) bcopy("abc", one, 4);
- X equal(one, "abc", 1); /* Simple copy. */
- X
- X (void) strcpy(one, "abcdefgh");
- X (void) bcopy("xyz", one+1, 2);
- X equal(one, "axydefgh", 2); /* Basic test. */
- X
- X (void) strcpy(one, "abc");
- X (void) bcopy("xyz", one, 0);
- X equal(one, "abc", 3); /* Zero-length copy. */
- X
- X (void) strcpy(one, "hi there");
- X (void) strcpy(two, "foo");
- X (void) bcopy(one, two, 9);
- X equal(two, "hi there", 4); /* Just paranoia. */
- X equal(one, "hi there", 5); /* Stomped on source? */
- X
- X /*
- X * bzero
- X */
- X it = "bzero";
- X (void) strcpy(one, "abcdef");
- X bzero(one+2, 2);
- X equal(one, "ab", 1); /* Basic test. */
- X equal(one+3, "", 2);
- X equal(one+4, "ef", 3);
- X
- X (void) strcpy(one, "abcdef");
- X bzero(one+2, 0);
- X equal(one, "abcdef", 4); /* Zero-length copy. */
- X
- X /*
- X * bcmp - somewhat like memcmp
- X */
- X it = "bcmp";
- X check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
- X check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
- X check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
- X check(bcmp("abce", "abcd", 4) != 0, 4);
- X check(bcmp("alph", "beta", 4) != 0, 5);
- X check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
- X check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
- X
- X#ifdef ERR
- X /*
- X * strerror - VERY system-dependent
- X */
- X it = "strerror";
- X f = open("/", 1); /* Should always fail. */
- X check(f < 0 && errno > 0 && errno < sys_nerr, 1);
- X equal(strerror(errno), sys_errlist[errno], 2);
- X#ifdef UNIXERR
- X equal(strerror(errno), "Is a directory", 3);
- X#endif
- X#ifdef BERKERR
- X equal(strerror(errno), "Permission denied", 3);
- X#endif
- X#endif
- X}
- END_OF_FILE
- if test 19922 -ne `wc -c <'libc/strings/tester.c'`; then
- echo shar: \"'libc/strings/tester.c'\" unpacked with wrong size!
- fi
- # end of 'libc/strings/tester.c'
- fi
- if test -f 'rnews/headers.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rnews/headers.c'\"
- else
- echo shar: Extracting \"'rnews/headers.c'\" \(18247 characters\)
- sed "s/^X//" >'rnews/headers.c' <<'END_OF_FILE'
- X/*
- X * Usenet header parsing and generation (see RFCs 850 & 822;
- X * for a second opinion, see The Hideous Name by Pike & Weinberger).
- X *
- X * Headers are parsed and modified and copied in one pass.
- X * Nevertheless, this file is split into two pieces: header parsing
- X * and remembering (aka eating) and header copying (aka munging).
- X * The split is marked and the two pieces are fairly independent.
- X *
- X * --- a quick tour of RFC 850 headers. Hold on tight ---
- X *
- X * mandatory headers follow:
- X * Path: ucbvax!ukc!decvax!mcvax!ih*!kaist!mh*!ho*!brahms!nsu # must prepend to
- X * From: whosit@brahms.b.uc.berkeley.edu.BERKELEY.EDU.uucp (Arthur ``Two-Sheds'' Jackson)
- X * Newsgroups: talk.philosophy.meaning.meaning
- X * Subject: Re: RE: re: rE: Orphaned Response - (nf) # previously Title:
- X * Date: Sat, 25-Dec-86 04:05:06 GMT # previously Posted:
- X * Message-ID: <unique@brahms.b.uc.berkeley.edu.BERKELEY.EDU.uucp> # previously Article-I.D.:
- X *
- X * optional headers follow:
- X * Relay-Version: C;utcs # must replace; must be 1st (recently demoted)
- X * Posting-Version: version C alpha;site utcs.uucp # (recently demoted)
- X * Date-Received: Sat, 25-Jan-87 12:34:56 GMT # must replace or snuff * # previously Received:
- X * Organization: UCB society for arguing the meaning of meaning
- X * Distribution: ucb
- X * Sender: twosheds@arpa.b.uc.berkeley.edu.BERKELEY.EDU.uucp
- X * Followup-To: talk.tv.i.love.lucy
- X * Control: newgroup talk.philosophy.meaning.meaning.meaning # magic; not for the uninitiated
- X * References: <345.wanker@isi-wankers.gov> <123.toadsexers@kcl-cs.uk>
- X * Reply-To: info-wankers@wankvax.b.uc.berkeley.edu.BERKELEY.EDU.uucp
- X * Expires: Sun, 31-dec-99 23:59:59 GMT
- X * Approved: kinsey@Uchicago.uucp # the mark of the moderator
- X * Lines: 6766 # redundant & pointless `wc -l`
- X *
- X * new headers not (yet?) in RFC850 follow:
- X * Summary: It was a dark and stormy night, # retain
- X * Keywords: toadsexing, ether, tetanus # retain
- X * Nf-*: transmitted via Notesviles # might snuff
- X *
- X * abusive & silly non-RFC-850 headers follow:
- X * Sccs-Id: @(#) 5.2.vax.2.women.only rob 3/5/83
- X * Hideous-Name: psuvax1!rhea::@brl.arpa:ucbvax!mit-mc%udel-relay.arpa@chris:umcp-cs::udel-relay%csnet-relay.vision.ubc.cdn
- X * Shoe-Size: 8
- X * Header-Questions-To: mark@pavo.cb.d.osg.cb.cbosgd.att.com.uucp
- X * Upas-To: eric@vax.b.uc.berkeley.edu.BERKELEY.EDU.uucp
- X * V9-Capable-Machines-To: utstat!geoff
- X * Uglix-Version: 5.3.vax.1.4/7/85.21:37:45.binary.only
- X *
- X * --- Ah well, it will only get worse. ---
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <sys/types.h>
- X#include "news.h"
- X#include "headers.h"
- X
- X#ifndef DEFDIST
- X#define DEFDIST "world" /* default Distribution: */
- X#endif
- X#ifndef DEFMSGID
- X#define DEFMSGID "<wanker@isi-wankers.isi.usc.edu>"
- X#endif
- X
- X#define JUNK "junk"
- X#define ALL "all"
- X
- X#define OLDCNTRL "all.all.ctl"
- X
- X/*
- X * Derivation: 752 is a large header, 120 is approx. size of *-Version because
- X * this rnews throws them away. HDRMEMSIZ can be too small if
- X * memory is tight and will only hurt performance.
- X */
- X#ifndef HDRMEMSIZ
- X#ifndef notdef
- X#define HDRMEMSIZ 8192 /* room for headers */
- X#else
- X#define HDRMEMSIZ (752-120)
- X#endif /* notdef */
- X#endif /* HDRMEMSIZ */
- X
- X /* from here down are recognised in eatheaders() */
- Xstatic char ctlnm[] = "Control:";
- Xstatic char distrnm[] = "Distribution:";
- Xstatic char appnm[] = "Approved:";
- Xstatic char subjnm[] = "Subject:";
- Xstatic char msgnm[] = "Message-ID:";
- Xstatic char artidnm[] = "Article-I.D.:"; /* obsolete Message-ID: */
- X /* from here down recognised by mungehdrs() */
- Xstatic char pathnm[] = "Path:"; /* so we can extend it (damn) */
- Xstatic char ngsnm[] = "Newsgroups:"; /* to clone for Xref */
- X /* down to here recognised by eatheaders() */
- Xstatic char xrefnm[] = "Xref:"; /* to *replace* Xref (damn!)*/
- X /*
- X * the following noxious headers are deleted because
- X * neighbours still send them and they are big.
- X * in an ideal world, they wouldn't be sent and thus
- X * we wouldn't need to delete them.
- X */
- X/* TODO: what about Posted: and Article-I.D.:? */
- Xstatic char datercvnm[] = "Date-Received:"; /* so we can snuff it */
- Xstatic char rcvnm[] = "Received:"; /* obsolete Date-Received: */
- Xstatic char rlyversnm[] = "Relay-Version:"; /* so we can snuff it */
- Xstatic char postversnm[] = "Posting-Version:"; /* so we can snuff it */
- X /* down to here recognised by mungehdrs() */
- X
- X
- X/* TODO: permit multiples of hdrprs and hpsp */
- Xstruct hdrparsestate {
- X char **prevvalp; /* points at previous header value string */
- X short prevhist; /* previous line was a header line */
- X short nextcont; /* next line must be a header continuation */
- X short newnextcont; /* nextcont for next line, based on this line */
- X char hdraccum[HDRMEMSIZ+MAXLINE];
- X char *endlnp; /* pointer to end of input buffer - 1 */
- X};
- Xstatic struct hdrparsestate hdrprs = { 0, NO, NO, 0 }; /* parser state */
- Xstatic struct hdrparsestate *hpsp = &hdrprs;
- X/* end of parser state */
- X
- X
- Xstatic int debug = NO;
- X
- X/* forward decls */
- Xchar *skipsp();
- X
- X/*
- X * --- common header code start ---
- X */
- X
- Xhdrdebug(state)
- Xint state;
- X{
- X debug = state;
- X}
- X
- Xhdrinit(hdrs) /* zero all pointers in hdrs */
- Xregister struct headers *hdrs;
- X{
- X hdrs->h_subj = NULL;
- X hdrs->h_ngs = NULL;
- X hdrs->h_files[0] = '\0';
- X hdrs->h_distr = NULL;
- X hdrs->h_ctlcmd = NULL;
- X hdrs->h_approved = NULL;
- X hdrs->h_msgid = NULL;
- X hdrs->h_artid = NULL;
- X hdrs->h_expiry = NULL;
- X hdrs->h_path = NULL;
- X hdrs->h_tmpf[0] = '\0';
- X hdrs->h_unlink = NO;
- X hdrs->h_filed = NO;
- X hdrs->h_xref = NO;
- X hdrs->h_octlchked = NO;
- X hdrs->h_oldctl = NO;
- X hdrs->h_accum = NULL;
- X hdrs->h_charswritten = 0;
- X}
- X
- Xstatic int
- Xoldctl(hdrs) /* true iff ngs are OLDCNTRL (cache in hdrs) */
- Xregister struct headers *hdrs;
- X{
- X if (!hdrs->h_octlchked) { /* don't know yet */
- X /* TODO: special case this, avoid ngmatch */
- X hdrs->h_oldctl = ngmatch(OLDCNTRL, hdrs->h_ngs);
- X hdrs->h_octlchked = YES; /* now we know */
- X }
- X return hdrs->h_oldctl;
- X}
- X
- Xint
- Xhdrmutate(hdrs, buffer, tfp) /* eat & munge headers */
- Xstruct headers *hdrs;
- Xchar *buffer;
- XFILE **tfp;
- X{
- X eatheaders(hdrs, buffer); /* mungehdrs needs n_ngs set */
- X return mungehdrs(buffer, tfp, hdrs); /* save or write hdr */
- X}
- X
- X/*
- X * --- header parsing and remembering starts here ---
- X */
- X
- X/*
- X * Reset internal state of header parser.
- X * (Empty the stomach of partially-digested headers. Waarrrgggh!)
- X */
- Xhdrwretch()
- X{
- X hpsp->prevvalp = NULL;
- X hpsp->prevhist = NO;
- X hpsp->nextcont = NO;
- X}
- X
- X/*
- X * Parse RFC822/850 header into "hdrs". Retain significant values.
- X * Assumes ishdr has been called first.
- X */
- Xeatheaders(hdrs, line)
- Xregister struct headers *hdrs;
- Xregister char *line;
- X{
- X /*
- X * One would really like to use a loop through a structure here,
- X * but it's hard because one can't initialise a static struct
- X * with e.g. &hdrs->h_path.
- X */
- X if (!contin(line) &&
- X !hdrmatch(line, pathnm, STRLEN(pathnm), &hdrs->h_path) &&
- X !hdrmatch(line, msgnm, STRLEN(msgnm), &hdrs->h_msgid) &&
- X !hdrmatch(line, artidnm,STRLEN(artidnm),&hdrs->h_artid) && /* obs. */
- X !hdrmatch(line, subjnm, STRLEN(subjnm), &hdrs->h_subj) &&
- X !hdrmatch(line, ngsnm, STRLEN(ngsnm), &hdrs->h_ngs) &&
- X !hdrmatch(line, distrnm,STRLEN(distrnm),&hdrs->h_distr) &&
- X !hdrmatch(line, appnm, STRLEN(appnm), &hdrs->h_approved) &&
- X !hdrmatch(line, ctlnm, STRLEN(ctlnm), &hdrs->h_ctlcmd)) {
- X static char *dummy = NULL;
- X
- X /*
- X * silly header - just set hpsp->prevvalp for contin()
- X * so that unrecognised headers may be continued.
- X */
- X if (dummy != NULL)
- X free(dummy);
- X dummy = strsave(""); /* may be realloced in contin() */
- X hpsp->prevvalp = &dummy; /* ditto */
- X }
- X hpsp->nextcont = hpsp->newnextcont; /* set nextcont for next line */
- X}
- X
- Xhdrdeflt(hdrs) /* default missing header values */
- Xregister struct headers *hdrs;
- X{
- X /*
- X * if strsave ever returns NULL on failure, instead of exiting,
- X * then the following calls need to check for failure.
- X */
- X if (hdrs->h_ngs == NULL)
- X hdrs->h_ngs = strsave(JUNK);
- X if (hdrs->h_msgid == NULL && hdrs->h_artid != NULL)
- X hdrs->h_msgid = strsave(hdrs->h_artid);
- X if (hdrs->h_msgid == NULL)
- X hdrs->h_msgid = strsave(DEFMSGID);
- X if (hdrs->h_expiry == NULL)
- X hdrs->h_expiry = strsave("-"); /* - means "default" */
- X if (hdrs->h_subj == NULL)
- X hdrs->h_subj = strsave("");
- X
- X /*
- X * Control message backwards compatibility, and I mean *backwards*.
- X * We're talking stone age here; we're probably talking A news: if
- X * no Control: header exists and the newsgroup matches all.all.ctl,
- X * use the Subject: as the control message.
- X *
- X * Since RFC 850 is vague on the subject, we will henceforth
- X * internally (but not on disk), treat the Newsgroup: value as
- X * foo.bar, not foo.bar.ctl. This simplifies the rest of
- X * processing somewhat.
- X */
- X if (hdrs->h_ctlcmd == NULL && oldctl(hdrs)) {
- X hdrs->h_ctlcmd = strsave(hdrs->h_subj);
- X hdrs->h_ngs[strlen(hdrs->h_ngs) - STRLEN(".ctl")] = '\0';
- X }
- X
- X if (hdrs->h_ctlcmd != NULL) /* control message */
- X hdrs->h_octlchked = NO; /* invalidate old comparison */
- X if (hdrs->h_distr == NULL)
- X hdrs->h_distr = strsave(DEFDIST);
- X}
- X
- Xstatic int
- Xiscontin(s) /* is s an RFC 822 header continuation? */
- Xregister char *s;
- X{
- X return hpsp->nextcont || hpsp->prevhist && iswhite(*s);
- X}
- X
- Xint
- Xishdr(s) /* is s an RFC 822 header line? */
- Xchar *s;
- X{
- X register char *cp = s;
- X
- X if (iscontin(s))
- X hpsp->prevhist = YES;
- X else {
- X register int c;
- X
- X /* look for first of NUL, whitespace, colon */
- X while ((c = *cp) != '\0' && !(isascii(c) && isspace(c)) &&
- X c != ':')
- X ++cp;
- X hpsp->prevhist = (c == ':' && cp > s); /* colon not 1st char */
- X }
- X /*
- X * If this is a header line and there is no trailing newline,
- X * assume fgets couldn't fit a very long header into the buffer
- X * for header lines, so the next line fgets sees must be a
- X * continuation of this line.
- X */
- X if (hpsp->prevhist) {
- X#ifndef DIRTYHDRCONT
- X INDEX(cp, '\n', cp);
- X hpsp->newnextcont = (cp == NULL); /* no \n -> continue */
- X#else /* DIRTYHDRCONT */
- X hpsp->newnextcont =
- X *hpsp->endlnp != '\0' && *hpsp->endlnp != '\n';
- X#endif /* DIRTYHDRCONT */
- X } else
- X hpsp->newnextcont = NO;
- X return hpsp->prevhist;
- X}
- X
- Xint
- Xcontin(line) /* append continuation value to old value */
- Xchar *line;
- X{
- X /*
- X * If there is a previous header value and this line starts
- X * with whitespace other than a newline, realloc *hpsp->prevvalp
- X * with enough space for the old value, the new value and a NUL.
- X * Then append the new value.
- X */
- X if (hpsp->prevvalp != NULL && iscontin(line)) {
- X char *valp = /* skipsp */ (line); /* continuation value */
- X
- X /* hpsp->prevvalp was previously set in hdrmatch() or eatheaders() */
- X *hpsp->prevvalp = realloc(*hpsp->prevvalp,
- X (unsigned)strlen(*hpsp->prevvalp) + strlen(valp) + 1);
- X if (*hpsp->prevvalp == NULL)
- X warning("realloc failed in contin", "");
- X else {
- X (void) strcat(*hpsp->prevvalp, valp);
- X trim(*hpsp->prevvalp); /* remove trailing newline */
- X }
- X return YES;
- X } else
- X return NO;
- X}
- X
- X/*
- X * Match line with keyword (return truth value).
- X * If it matches, store the value in *malloc'ed memory* (N.B.)
- X * and set *ptrp to point there. freeheader() will free this memory.
- X */
- Xint
- Xhdrmatch(line, keyword, keylen, ptrp)
- Xregister char *line, *keyword;
- Xregister int keylen; /* an optimisation */
- Xregister char **ptrp; /* make it point at valuep */
- X{
- X#ifdef notdef
- X register int keylen = strlen(keyword); /* the slower way */
- X#endif
- X register int match = STREQN(line, keyword, keylen);
- X
- X if (match && *ptrp != NULL) /* value already set */
- X free(*ptrp); /* return storage */
- X if (match && (*ptrp = strsave(skipsp(&line[keylen]))) != NULL) {
- X trim(*ptrp); /* remove trailing new line */
- X hpsp->prevvalp = ptrp; /* for contin() */
- X }
- X return match;
- X}
- X
- Xfreeheaders(hdrs) /* free (assumed) malloced storage */
- Xregister struct headers *hdrs;
- X{
- X nnfree(&hdrs->h_subj);
- X nnfree(&hdrs->h_ngs);
- X nnfree(&hdrs->h_distr);
- X nnfree(&hdrs->h_ctlcmd);
- X nnfree(&hdrs->h_approved);
- X nnfree(&hdrs->h_msgid);
- X nnfree(&hdrs->h_artid);
- X nnfree(&hdrs->h_expiry);
- X nnfree(&hdrs->h_path);
- X}
- X
- Xnnfree(mempp) /* free non-null pointer's memory */
- Xregister char **mempp; /* pointer to malloc'ed ptr. */
- X{
- X if (*mempp != NULL) {
- X free(*mempp);
- X *mempp = NULL;
- X }
- X}
- X
- Xint
- Xemitxref(tf, hdrs) /* splat out an Xref: line from Newsgroups: */
- Xregister FILE *tf;
- Xstruct headers *hdrs;
- X{
- X register char *slashp;
- X int status = ST_OKAY;
- X char xrefs[MAXLINE];
- X
- X if (!hdrs->h_xref) { /* this article has no Xref: yet */
- X hdrs->h_xref = YES;
- X (void) strcpy(xrefs, hdrs->h_files);
- X /* turn slashes into colons for the benefit of rn */
- X for (slashp = xrefs; (slashp = index(slashp, FNDELIM)) != NULL; )
- X *slashp++ = ':';
- X if (fprintf(tf, "%s %s %s\n", xrefnm, hostname(), xrefs) == EOF)
- X status = fulldisk(status|ST_DROPPED,
- X (hdrs->h_unlink? hdrs->h_tmpf: hdrs->h_files));
- X }
- X return status;
- X}
- X
- X/*
- X * --- header munging (copying) starts here ---
- X */
- X
- X/*
- X * Copy headers and munge a few. Assumes eatheaders has been called.
- X *
- X * Don't copy Date-Received nor *-Version nor Xref.
- X * Prepend hostname! to Path: value.
- X * Recognise Newsgroups: and if more than one, generate Xref: &
- X * leave holes for the article numbers - fileart will fill them in.
- X * (Make rn look in history instead?)
- X *
- X * (Header munging should be a felony. When they make me dictator,
- X * it will be: punishable by having to use 4.2BSD networking.)
- X *
- X * New strategy: pile up headers into a static buffer until
- X * end of buffer (next line might not fit) [checked in hdrsave()]; end of
- X * headers, file or byte count [checked in cparttofp].
- X * During reading, discard swill headers. Path: is munged on output.
- X * Copy (save) or discard header lines.
- X */
- Xint
- Xmungehdrs(buffer, tfp, hdrs)
- Xregister char *buffer;
- Xregister FILE **tfp;
- Xstruct headers *hdrs;
- X{
- X struct vilesthdrs {
- X char *vh_name;
- X unsigned vh_len;
- X };
- X register struct vilesthdrs *vhp;
- X static struct vilesthdrs vilest[] = {
- X datercvnm, STRLEN(datercvnm),
- X rcvnm, STRLEN(rcvnm),
- X rlyversnm, STRLEN(rlyversnm),
- X postversnm, STRLEN(postversnm),
- X xrefnm, STRLEN(xrefnm),
- X NULL, 0
- X };
- X
- X if (debug)
- X (void) fputs(buffer, stderr);
- X /*
- X * Toss the most vile of the trash headers.
- X * In an ideal world, this code wouldn't exist.
- X */
- X for (vhp = vilest; vhp->vh_name != NULL; vhp++)
- X if (STREQN(buffer, vhp->vh_name, (int)vhp->vh_len))
- X return ST_OKAY;
- X /* wasn't vile; save it. *tfp may be NULL. Be Prepared. */
- X return hdrsave(buffer, hdrs, tfp); /* may set *tfp */
- X}
- X
- X/*
- X * If headers already dumped (hdrs->h_filed), just write to *tfp.
- X * If there is room, stash "hdr" away until Newsgroups: is seen,
- X * then open the first article link (on *tfp)
- X * and dump the saved headers to it.
- X * Copy into hdrs->h_accum (TODO: read in directly, iff high on profile).
- X * TODO: may want an end-of-accum pointer for speed, iff high on profile.
- X */
- Xint
- Xhdrsave(hdr, hdrs, tfp)
- Xchar *hdr;
- Xregister struct headers *hdrs;
- XFILE **tfp;
- X{
- X int status = ST_OKAY;
- X unsigned hdrlen = strlen(hdr);
- X
- X if (hdrs->h_filed) /* *tfp != NULL */
- X return emithdr(hdrs, hdr, *tfp);
- X if (hdrs->h_accum == NULL) {
- X hdrs->h_accum = hpsp->hdraccum; /* primitive storage allocation */
- X hdrs->h_accum[0] = '\0';
- X hdrs->h_bytesleft = sizeof hpsp->hdraccum;
- X }
- X if (hdrs->h_bytesleft > hdrlen) { /* it fits! */
- X (void) strcat(hdrs->h_accum, hdr); /* whomp it on the end */
- X hdrs->h_bytesleft -= hdrlen;
- X } else { /* no room; barf out headers */
- X status |= hdrdump(tfp, hdrs, NO); /* don't trigger fileart */
- X if (*tfp != NULL)
- X status |= emithdr(hdrs, hdr, *tfp);
- X }
- X return status;
- X}
- X
- Xstatic int
- Xemithdr(hdrs, hdr, tf) /* munge Path: else just dump the header (hdr) */
- Xregister struct headers *hdrs;
- Xchar *hdr;
- XFILE *tf;
- X{
- X register int status = ST_OKAY;
- X
- X if (STREQN(hdr, pathnm, STRLEN(pathnm))) { /* Path: */
- X register int hdrbytes;
- X register char *oldpath;
- X
- X oldpath = skipsp(&hdr[STRLEN(pathnm)]);
- X hdrbytes = fprintf(tf, "%s %s!", pathnm, hostname());
- X if (hdrbytes == EOF || fputs(oldpath, tf) == EOF)
- X status = fulldisk(status|ST_DROPPED,
- X (hdrs->h_unlink? hdrs->h_tmpf: hdrs->h_files));
- X else
- X hdrs->h_charswritten += hdrbytes + strlen(oldpath);
- X } else { /* ordinary header */
- X if (fputs(hdr, tf) == EOF)
- X status = fulldisk(status|ST_DROPPED,
- X (hdrs->h_unlink? hdrs->h_tmpf: hdrs->h_files));
- X else
- X hdrs->h_charswritten += strlen(hdr);
- X }
- X return status;
- X}
- X
- X/*
- X * Barf out headers after opening on *tfp either a temporary file (using
- X * mktemp(3)) or the first article link, based on the h_ngs & nxtartnum();
- X * set h_tmpf to which ever name is opened. Modify Path: value on the way.
- X */
- Xint
- Xhdrdump(tfp, hdrs, allhdrsseen)
- XFILE **tfp;
- Xregister struct headers *hdrs;
- Xint allhdrsseen;
- X{
- X int status = ST_OKAY;
- X
- X if (hdrs->h_filed)
- X return status;
- X /*
- X * If all headers were seen & the group was not an old backward-
- X * compatible control group (which won't exist), then open the
- X * first link, link to the rest, generate Xref:, else open a
- X * temporary name and write the article there
- X * (it will get filed later in insart()).
- X */
- X if (allhdrsseen && hdrs->h_ngs != NULL && !oldctl(hdrs))
- X status |= fileart(hdrs, tfp, 1);
- X else {
- X (void) strcpy(hdrs->h_tmpf, SPOOLTMP);
- X (void) mktemp(hdrs->h_tmpf); /* make a temporary name */
- X hdrs->h_unlink = 1; /* unlink it when done */
- X if ((*tfp = fopen(hdrs->h_tmpf, "w")) == NULL) {
- X warning("can't open temporary name `%s'", hdrs->h_tmpf);
- X status |= ST_DROPPED;
- X }
- X }
- X if (*tfp != NULL) {
- X register char *line, *nlp;
- X register int saved;
- X
- X /* this is a deadly tedious job and I really should automate it */
- X for (line = hdrs->h_accum; line != NULL && line[0] != '\0';
- X line = nlp) {
- X /*
- X * Could this call on INDEX be eliminated without
- X * restricting the number of header lines?
- X */
- X INDEX(line, '\n', nlp);
- X if (nlp != NULL) {
- X ++nlp; /* byte after \n is NUL or text */
- X saved = *nlp;
- X *nlp = '\0'; /* will be restored below */
- X }
- X if (emithdr(hdrs, line, *tfp) == EOF) /* dump saved headers */
- X status = fulldisk(status|ST_DROPPED,
- X (hdrs->h_unlink? hdrs->h_tmpf: hdrs->h_files));
- X if (nlp != NULL)
- X *nlp = saved; /* restore */
- X }
- X }
- X#ifdef notdef
- X hdrs->h_accum = NULL; /* primitive memory deallocation */
- X#endif
- X return status;
- X}
- END_OF_FILE
- if test 18247 -ne `wc -c <'rnews/headers.c'`; then
- echo shar: \"'rnews/headers.c'\" unpacked with wrong size!
- fi
- # end of 'rnews/headers.c'
- fi
- echo shar: End of archive 12 \(of 14\).
- ## End of shell archive.
- exit 0
-